/*
 * AgendaDetailController.java
 *
 * Created on 2007��11��28��, ����1:30
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package com.microweb.toastmaster.webapp.action;

import com.lowagie.text.pdf.AcroFields;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;
import com.microweb.toastmaster.Constants;
import com.microweb.toastmaster.model.Actor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.microweb.toastmaster.model.Agenda;
import com.microweb.toastmaster.model.LabelValue;
import com.microweb.toastmaster.model.Speech;
import com.microweb.toastmaster.model.TMRole;
import com.microweb.toastmaster.model.viewwrapper.AgendaWrapper;
import com.microweb.toastmaster.service.AgendaManager;
import com.microweb.toastmaster.service.TMRoleManager;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

/**
 * 
 * @author watercup
 */
public class AgendaDetailController implements Controller {

	private final Log log = LogFactory.getLog(AgendaDetailController.class);
	private AgendaManager agendaManager = null;
	private TMRoleManager TMRoleManager = null;

	public void setAgendaManager(AgendaManager agendaManager) {
		this.agendaManager = agendaManager;
	}

	public void setTMRoleManager(TMRoleManager TMRoleManager) {
		this.TMRoleManager = TMRoleManager;
	}

	public ModelAndView handleRequest(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		if (log.isDebugEnabled()) {
			log.debug("entering 'handleRequest' method...");
		}

		String id = request.getParameter("id");
		log.debug("parameter id = " + id);
		Agenda agenda = null;

		if (id != null && id.trim().length() != 0)
			agenda = agendaManager.getAgenda(id);

		List actors = getActors(agenda);

		ModelAndView mav = null;
		String presentationType = request.getParameter("presentationtype");
		String strDir = request.getSession().getServletContext().getRealPath("/");
		if (presentationType != null && presentationType.equals("pdf")) {
			if (agenda.getActorByRolename(Constants.ROLENAME_SPEAKER3) == null) {
				generatePdf(agenda, strDir, false);
			} else {
				generatePdf(agenda, strDir, true);
			}

			mav = new ModelAndView("redirect:" + getFileName(agenda));
		} else {
			mav = new ModelAndView("agenda");
			mav.addObject("agenda", new AgendaWrapper(agenda));
			mav.addObject("actors", actors);
		}

		return mav;
	}

	/**
	 * get a list of LabelValue which stores role name as its lable and user
	 * name as its value.
	 * 
	 * if no user take certain role in this agenda, the value of corresponding
	 * LabelValue will not be set.
	 */
	private List<LabelValue> getActors(Agenda agenda) {
		Set<?> actors = agenda.getActors();
		List<LabelValue> values = new ArrayList<LabelValue>();
		List<?> tmroles = TMRoleManager.getTMRoles(null);

		for (int i = 0; i < tmroles.size(); i++) {
			TMRole tmrole = (TMRole) tmroles.get(i);
			LabelValue value = new LabelValue();
			value.setLabel(tmrole.getName());

			Iterator<?> it = actors.iterator();
			while (it.hasNext()) {
				Actor actor = (Actor) it.next();
				if (tmrole.getName().equals(actor.getTMRole().getName())) {
					value.setValue(actor.getUser().getFullName());
					break;
				}
			}

			log.debug("add value : " + value);
			values.add(value);
		}

		return values;
	}

	private String getPdfFieldname(String shortName) {
		return Constants.PDF_FIELD_HEADING + shortName + "[0]";
	}

	private String getFileName(Agenda agenda) {
		Locale locale = Locale.US;
		SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd", locale);
		String strDate = formatter.format(agenda.getDate());
		return "agenda" + strDate + ".pdf";
	}

	private void generatePdf(Agenda agenda, String dirPath,
			boolean bThreeSpeaker) {

		log.debug("start generating pdf file for agenda: " + agenda.getId());
		String templeteFile = Constants.PDF_TEMPLETE2;
		if (bThreeSpeaker)
			templeteFile = Constants.PDF_TEMPLETE3;

		log.debug("loading file [ " + templeteFile + " ] as templete.");
		try {
			File pdfFile = new File(dirPath + File.separator
					+ getFileName(agenda));
			log.debug("write to file: " + pdfFile.getAbsolutePath());
			PdfReader reader = new PdfReader(templeteFile);
			PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(
					pdfFile));
			AcroFields form = stamper.getAcroFields();

			Locale locale = Locale.US;
			SimpleDateFormat formatter = new SimpleDateFormat(
					"EEEE, MMMM d, yyyy '-- 4:00-5:00pm'", locale);
			String strDate = formatter.format(agenda.getDate());
			log.debug("date string: " + strDate);
			form.setField(getPdfFieldname(Constants.PDF_DATE), strDate);
			form.setField(getPdfFieldname(Constants.PDF_THEME),
					Constants.PDF_THEME_HEADING + agenda.getTheme());
			form.setField(getPdfFieldname(Constants.PDF_PHRASE_TITLE),
					Constants.PDF_PHRASE_HEADING
							+ agenda.getPhrase().getPhrase());
			form.setField(getPdfFieldname(Constants.PDF_PHRASE), agenda
					.getPhrase().getPhrase());
			form.setField(getPdfFieldname(Constants.PDF_PHRASE_DEFINITION),
					Constants.PDF_DEFINITION_HEADING
							+ agenda.getPhrase().getDefinition());
			form.setField(getPdfFieldname(Constants.PDF_PHRASE_EXAMPLE),
					Constants.PDF_EXAMPLE_HEADING
							+ agenda.getPhrase().getExample());

			// set speeches
			Speech speech1 = agenda.getSpeech(new Integer(1));
			if (speech1 != null) {
				form.setField(getPdfFieldname(Constants.PDF_SPEECH1_TITLE),
						Constants.PDF_SPEECH_HEADING + speech1.getTitle());
				form.setField(getPdfFieldname(Constants.PDF_SPEECH1_CATEGORY),
						Constants.PDF_CATEGORY_HEADING
								+ speech1.getTMProject().getNumber().toString()
								+ ": " + speech1.getTMProject().getName());
			}

			Speech speech2 = agenda.getSpeech(new Integer(2));
			if (speech2 != null) {
				form.setField(getPdfFieldname(Constants.PDF_SPEECH2_TITLE),
						Constants.PDF_SPEECH_HEADING + speech2.getTitle());
				form.setField(getPdfFieldname(Constants.PDF_SPEECH2_CATEGORY),
						Constants.PDF_CATEGORY_HEADING
								+ speech2.getTMProject().getNumber().toString()
								+ ": " + speech2.getTMProject().getName());
			}

			// set all roles
			setRoleField(form, agenda, Constants.ROLENAME_PREZIDENT);
			setRoleField(form, agenda, Constants.ROLENAME_TOASTERMASTER);
			setRoleField(form, agenda, Constants.ROLENAME_AH_COUNTER);
			setRoleField(form, agenda, Constants.ROLENAME_EVALUATOR1);
			setRoleField(form, agenda, Constants.ROLENAME_EVALUATOR2);
			setRoleField(form, agenda, Constants.ROLENAME_GENERAL_EVALUATOR);
			setRoleField(form, agenda, Constants.ROLENAME_GRAMMARIAN);
			setRoleField(form, agenda, Constants.ROLENAME_SECRETARY);
			setRoleField(form, agenda, Constants.ROLENAME_SPEAKER1);
			setRoleField(form, agenda, Constants.ROLENAME_SPEAKER2);
			setRoleField(form, agenda, Constants.ROLENAME_TABLE_TOPIC_MASTER);
			setRoleField(form, agenda, Constants.ROLENAME_TIMER);
			setRoleField(form, agenda, Constants.ROLENAME_VIDEO_OPERATOR);
			setRoleField(form, agenda, Constants.ROLENAME_VOTE_COUNTER);

			if (bThreeSpeaker) {
				setRoleField(form, agenda, Constants.ROLENAME_EVALUATOR3);
				setRoleField(form, agenda, Constants.ROLENAME_SPEAKER3);

				Speech speech3 = agenda.getSpeech(new Integer(3));
				if (speech3 != null) {
					form.setField(getPdfFieldname(Constants.PDF_SPEECH3_TITLE),
							Constants.PDF_SPEECH_HEADING + speech3.getTitle());
					form.setField(
							getPdfFieldname(Constants.PDF_SPEECH3_CATEGORY),
							Constants.PDF_CATEGORY_HEADING
									+ speech3.getTMProject().getNumber()
											.toString() + ": "
									+ speech3.getTMProject().getName());
				}
			}

			stamper.setFormFlattening(true);
			stamper.close();
			log.debug("successfully generated pdf file.");

		} catch (Exception de) {
			de.printStackTrace();
		}
	}

	private void setRoleField(AcroFields form, Agenda agenda, String rolename)
			throws Exception {
		log.debug("writing " + rolename + " ...");
		form.setField(getPdfFieldname(rolename), agenda
				.getUsernameByRole(rolename));
	}

}
